﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;  //usado para administrar los hilos
using System.Collections;  //usado para ArrayList

using SistemaCenterQuimPost.Plantillas; //usado para hacer referencias a la fecha;
using SistemaCenterQuimPost.Reportes; //usado para imprimir la venta.
using SistemaCenterQuimPost.Entidad;  //Usado para instanciar objetos de clase Producto y agilizar el filtrado de descripción.
using System.Text.RegularExpressions; //usado para expresiones regulares. Filtrar descripciones
using SistemaCenterQuimPost.Control; //usado para validar datos.

using System.IO;    //3 referencias que son necesarias para el proceso de archivos.
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;



namespace SistemaCenterQuimPost.UI.PostCajero
{
    public partial class frmEmitirOrdenCompra : SistemaCenterQuimPost.Plantillas.frmPlantillaHijo
    {
        //------ATRIBUTOS-------------------------------
        
        private DataSet2 centerQuim;
        private DataSet2TableAdapters.ProductosTableAdapter productosTa;
        private DataSet2TableAdapters.Orden_de_CompraTableAdapter ordenTa;
        private DataSet2TableAdapters.ProductosxOrden_CompraTableAdapter productosxOrdenTa;
        private DataSet2TableAdapters.PostTableAdapter postTa;

        private bool refrescarResgProductos; //La primera vez debe refrescar el resgProductos.

        private ArrayList resgProductos; // colección usada para guardar Codigos de productos y descripción, se tiene una pequeña base de dato para realizar las busqueda mediante filtros más rapidamente.

        private Thread oHiloActualizarResgProductos; //hilos que son ejecutados concurrentemente con la aplicación.
        private Thread oHiloFiltrarDescripcion;

        private string estadoDelFormulario;


        //objeto para serializar los RegistroUsuario y RegistroListaPrecio en formato binario
        private BinaryFormatter aplicadorFormato = new BinaryFormatter(); //Clase que permite serializar objeto, es decir pasarlo a binario.
        private FileStream ordenCompraSalida; //clase que maneja la información sobre el archivo y la forma de abrirlo.

        //--------------------CONSTRUCTOR-------------------
        
        public frmEmitirOrdenCompra()
        {
            InitializeComponent();
            centerQuim = new DataSet2();
            productosTa = new DataSet2TableAdapters.ProductosTableAdapter();
            ordenTa = new DataSet2TableAdapters.Orden_de_CompraTableAdapter();
            productosxOrdenTa = new DataSet2TableAdapters.ProductosxOrden_CompraTableAdapter();
            postTa = new DataSet2TableAdapters.PostTableAdapter();

            estadoDelFormulario = "";

            refrescarResgProductos = true; //inicializamos a true, ya que la primera vez que trate de usar ResgProductos tendra que actualizar.

            this.resgProductos = new ArrayList();  //se inicializa la colección ArrayList que guardará una base de datos parcial.          

            this.oHiloActualizarResgProductos = new Thread(new ThreadStart(actualizarResgProductos)); //Instancia el hilo y lo delega al metodo actualizarResgProductos. 
            this.oHiloFiltrarDescripcion = new Thread(new ThreadStart(filtrarDescripcion));


        }

        //-----------------------ESTADOS---------------------
        private void frmEmitirOrdenCompra_Load(object sender, EventArgs e)
        {
            
            cargarGrilla();
            colorearGrilla();
            verificarCantidadMinima();

            estEsperandoOperacion();
        }

        
        private void estEsperandoOperacion() //estado luego de realizar una busqueda exitosa, agregar o editar. Es decir con datos en vista.
        {
            System.Windows.Forms.Control[] controlesHabilitados = { this.txtCodBarra, this.btnBusCodigo, this.txtDescripcion, this.btnBusDescripcion, this.btnProcesar };
            System.Windows.Forms.Control[] controlesDeshabilitados = { this.lstProductosCodBarra, this.lstProductosDescripcion };
            System.Windows.Forms.Control[] controlesVisibles = { };
            System.Windows.Forms.Control[] controlesInvisibles = { this.lstProductosCodBarra, this.lstProductosDescripcion, lblError };

            habilitarControles(controlesHabilitados);
            deshabilitarControles(controlesDeshabilitados);
            visibleControles(controlesVisibles);
            invisibleControles(controlesInvisibles);

            if (refrescarResgProductos) //si hace falta actualizar el refrescarResgProducto se realiza
            {
                ejecutarHiloActualizarResgProductos();

            }

            errorProvider1.Clear();  //se borran los errores, si habian.


            estadoDelFormulario = "estEsperandoOperacion";
        }

        //----------METODOS VARIOS-----------------------------

        //Virtual, permite redefinir en frmAltaProductosDisueltos y frmRecibirProductos
        protected virtual void actualizarResgProductos() //Se refresca el arrayList resgProductos
        {
            try
            {
                //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,...);
                productosTa.FillByNoGranel(centerQuim.Productos);

                resgProductos.Clear(); //Se vacia resgProductos (ArrayList)

                foreach (DataRow unaFila in centerQuim.Productos) //Se recorre todas las filas  del centerQuimDs.Productos y se cargan los productos al ArrayList
                {
                    resgProductos.Add(new Producto(Convert.ToString(unaFila[0]), Convert.ToString(unaFila[1])));

                }

                refrescarResgProductos = false;

            }
            catch (IndexOutOfRangeException)
            {
                //si llega a ocurrir esta excepcion no se tiene en cuenta. Podría no haber productos cargados y lanzaría esta excepción.

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }

        }

        protected void btnBusCodigo_Click(object sender, EventArgs e)  //método que se ejecuta cuando se presiona sobre el botón btnBusCodigo
        {
            eventoBusCodigo();

        }

        protected virtual void eventoBusCodigo()  //Se encapsula en un método para que pueda usar cuando se presiona Enter sobre el txtCodBarra en estado de busqueda o click en btnBusCodBarra.
        {

            //no hace falta que pregunte si txtCodBarra es blanco, ya que por la forma de filtrar no encontrará nada igual.                                

            if (refrescarResgProductos)   //si es necesario actualizar el resgProductos se lo hace sino no
            {
                ejecutarHiloActualizarResgProductos();  //ejecuta el hilo que actualiza el ResgProductos
            }

            filtrarCodigoBarra();


            if (lstProductosCodBarra.Items.Count == 0)  //el filtro no obtuvo coincidencias.
            {
                //Se informa que no se encontró nada 
                MessageBox.Show("Su consulta no ha arrojado resultados.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                //Como no encontró nada se deja en este estado.
                this.estEsperandoOperacion();
            }
            else
            {
                if (lstProductosCodBarra.Items.Count == 1)   //solo se encontró una sola coincidencia. No es necesario mostrar el lstProductosCodBarra. Directamente se muestra el producto.
                {
                    this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDescripcion y lanzará el evento TextChanged()

                    cargarProductoPorCodigo(this.txtCodBarra.Text.Trim());  //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.

                    estEsperandoOperacion(); //se deja en el estado necesario

                }
                else
                {
                    //si se obtuvo más de una coincidencia, solo se muestran éstas en lstProductosCodBarra, y espera a que el usuario seleccione una.

                    lstProductosCodBarra.Visible = true;
                    lstProductosCodBarra.Enabled = true;

                    //lstProductosCodBarra.Focus(); //se deja el foco en el dgvProductosCodBarra para que elija alguna coincidencia.

                    //lstProductosCodBarra.SelectedIndex=0;  //se deja seleccionado el primer items.
                }

            }

        }

        protected void ejecutarHiloActualizarResgProductos() // hilo para actualizar el atributo ResgProductos
        {
            if ((oHiloActualizarResgProductos.ThreadState == ThreadState.Unstarted) || (oHiloActualizarResgProductos.ThreadState == ThreadState.Stopped))
            {
                this.oHiloActualizarResgProductos = new Thread(new ThreadStart(actualizarResgProductos));
                this.oHiloActualizarResgProductos.Priority = ThreadPriority.Highest;
                this.oHiloActualizarResgProductos.Start();  //Se ejecuta el hilo para actualizar el atributo ResgProductos
            }
        }



        protected virtual void cargarProductoPorCodigo(string unCodBarra) //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.
        {
            try
            {
                //(ALE)HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,unCodBarra);
                productosTa.FillByCodigo(centerQuim.Productos, unCodBarra);

                seleccionarProductoGrilla(centerQuim.Productos[0].descripcion);

                //...
                //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected void filtrarCodigoBarra()  //Filtra y carga las descripciones (si las hay) en el lstProductos. Método que se ejecuta dentro de un hilo. 
        {

            this.oHiloActualizarResgProductos.Join(); //espera a que primero termine el oHiloActualizarResgProductos para proceder con el actual.

            lstProductosCodBarra.Items.Clear(); //vaciamos el lstProductosCodBarra por si tuviera descripciones anteriores.


            foreach (Producto unProducto in resgProductos) //buscamos las descripciones asociadas al código y la cargamos en el lstProductosCodBarra
            {
                if (this.txtCodBarra.Text.Trim() == unProducto.CodBarra)
                {
                    lstProductosCodBarra.Items.Add(unProducto.Descripcion);
                }

            }

        }

        protected void lstProductosCodBarra_DoubleClick(object sender, EventArgs e)  //captura en evento doble click sobre lstProductosCodBarra
        {
            procesarEleccionLstProductosCodBarra();
        }

        protected void procesarEleccionLstProductosCodBarra()  //se encapsulo para que se pueda usar con DoubleClick y Enter sobre el lstProductosCodBarra
        {
            try
            {
                this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDescripcion y lanzará el evento TextChanged()

                cargarProductoPorDescripcion(lstProductosCodBarra.SelectedItem.ToString()); //busca producto por descripción en la base de datos, y lo carga en los textBox.

                estEsperandoOperacion(); //se deja en el estado necesario

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        private void cargarProductoPorDescripcion(string unaDescripcion)  //busca el producto por descripción en la base de datos y lo carga en los textbox.
        {
            seleccionarProductoGrilla(unaDescripcion); //Selecciona el producto en la grilla.

        }

        private void seleccionarProductoGrilla(string unaDescripcion) //selecciona un producto de la grilla
        {

            int filaProducto = 0; //contador que almacenará la fila donde está el producto buscado.

            bool encontrado = false; //bandera que controla si se encontró el producto.

            foreach (DataGridViewRow row in dgvProductos.Rows) //se recorre todo el data grid, buscando el producto. Busqueda con centinela.
            {
                if (row.Cells[1].Value.ToString() == unaDescripcion)
                {
                    encontrado = true;

                    break;

                }else
                {
                    filaProducto++;
                }


            }

            if (encontrado) //si se encontró se selecciona el producto en la grilla.
            {
                dgvProductos.Rows[filaProducto].Selected = true;
                dgvProductos.CurrentCell = dgvProductos.Rows[filaProducto].Cells[0];
            }
            
            

        }

        protected void txtCodBarra_KeyDown(object sender, KeyEventArgs e)  //captura el evento KeyDown sobre el txtCodBarra.
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (estadoDelFormulario == "estEsperandoOperacion") //estado esperando operación o estado inicial
                {
                    eventoBusCodigo();

                }

            }
            else
            {
                if ((e.KeyCode == Keys.Down) & (lstProductosCodBarra.Items.Count > 0) & (estadoDelFormulario == "estEsperandoOperacion")) //Si se presiona para abajo y tiene a lstProductosDescripcion visible (es decir se encuentra esperando operacion y con items en la lista)
                {

                    lstProductosCodBarra.SetSelected(0, true); //se deja seleccionado el primer items
                    lstProductosCodBarra.Focus(); //Se deja el foco sobre este control para que seleccione un items.
                }
            }

        }

        protected void lstProductosCodBarra_Leave(object sender, EventArgs e) //Oculta automáticamente el lstProductosCodBarra cuando el control pierde el foco.
        {
            this.lstProductosCodBarra.Enabled = false;
            this.lstProductosCodBarra.Visible = false;
            this.lstProductosCodBarra.Items.Clear();
        }



        protected void txtDescripcion_TextChanged(object sender, EventArgs e) //evento que se desencadena cuando cambia el valor del TextBox
        {
            if (this.estadoDelFormulario == "estEsperandoOperacion") //el proceso es capturado solo si está en este estado.
            {
                eventoBusDescripcion();
            }

        }

        protected void eventoBusDescripcion()
        {
            if (txtDescripcion.Text != "") //Si txtDescripcion es distinto de blanco se realiza el procesamiento. Esto se realiza para no perder el tiempo en filtro innecesarios.
            {
                if (refrescarResgProductos)   //si es necesario actualizar el resgProductos se lo hace sino no
                {
                    ejecutarHiloActualizarResgProductos();
                }

                ejecutarHiloFiltrarDescripcion();

                if (lstProductosDescripcion.Items.Count == 0)  //el filtro no obtuvo coincidencias, no se muestra el lstProductosDescripcion
                {
                    lstProductosDescripcion.Visible = false;
                    lstProductosDescripcion.Enabled = false;

                }
                else
                {
                    lstProductosDescripcion.Visible = true; //si se obtuvo una o más coincidencia se muestran en lstProductosDescripcion, y espera a que el usuario seleccione una.
                    lstProductosDescripcion.Enabled = true;

                }

            }
            else  //Si txtDescripcion es blanco no se realiza el procesamiento
            {
                lstProductosDescripcion.Enabled = false;
                lstProductosDescripcion.Visible = false;
            }
        }

        protected void ejecutarHiloFiltrarDescripcion()
        {
            if ((this.oHiloFiltrarDescripcion.ThreadState == ThreadState.Unstarted) || (this.oHiloFiltrarDescripcion.ThreadState == ThreadState.Stopped))
            {
                this.oHiloFiltrarDescripcion = new Thread(new ThreadStart(filtrarDescripcion)); //Instancia el hilo y lo delega al metodo filtrarDescripcion. 
                this.oHiloFiltrarDescripcion.Priority = ThreadPriority.AboveNormal;
                this.oHiloFiltrarDescripcion.Start();  //hilo que filtra las descripciones asociadas al valor del txtDescripcion y lo carga en lstProductosDescripcion
            }

        }


        protected void filtrarDescripcion()
        {
            //this.oHiloActualizarResgProductos.Join(); //espera a que primero termine el oHiloActualizarResgProductos para proceder con el actual.

            lstProductosDescripcion.Items.Clear(); //vaciamos el lstProductosDescripcion por si tuviera descripciones anteriores.

            try
            {
                foreach (Producto unProducto in resgProductos) //buscamos las descripciones que coinciden con (al menos una palabra o letra + txtDescripcion.text + ninguna o muchas palabras o letras) y la cargamos en el lstProductosDescripcion
                {

                    if (Regex.Match(unProducto.Descripcion, txtDescripcion.Text.Trim().ToUpper()).Success)
                    {
                        lstProductosDescripcion.Items.Add(unProducto.Descripcion);
                    }

                }
            }
            catch (InvalidExpressionException)
            {

            }

            catch (Exception)
            {
                txtDescripcion.Text = "";

            }

        }

        protected void txtDescripcion_KeyDown(object sender, KeyEventArgs e) //Método que captura el evento de presión de una tecla sobre txtDescripcion
        {
            if ((e.KeyCode == Keys.Down) & (lstProductosDescripcion.Items.Count > 0) & (estadoDelFormulario == "estEsperandoOperacion")) //Si se presiona para abajo y tiene a lstProductosDescripcion visible (es decir se encuentra esperando operacion y con items en la lista)
            {

                lstProductosDescripcion.SetSelected(0, true); //se deja seleccionado el primer items
                lstProductosDescripcion.Focus(); //Se deja el foco sobre este control para que seleccione un items.

            }

        }



        protected void lstProductosDescripcion_Leave(object sender, EventArgs e) //Oculta automáticamente el lstProductosDescripcion cuando el control pierde el foco.
        {
            this.lstProductosDescripcion.Enabled = false;
            this.lstProductosDescripcion.Visible = false;
        }

        protected void lstProductosDescripcion_DoubleClick(object sender, EventArgs e) //evento que captura la elección de un item en el lstProductosDescripcion
        {
            procesarEleccionLstProductosDescripcion();
        }


        protected void procesarEleccionLstProductosDescripcion()  //Se encapsula para que capture Double click y Enter sobre  lstProductosDescripcion
        {
            try
            {
                this.estadoDelFormulario = "Buscando";

                cargarProductoPorDescripcion(lstProductosDescripcion.SelectedItem.ToString()); //busca producto por descripción y lo carga en los textBox.

                estEsperandoOperacion(); //se deja en el estado necesario

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }

        protected void btnBusDescripcion_Click(object sender, EventArgs e) //captura el evento Click sobre el boton btnBusDescripcion
        {
            eventoBusDescripcion();
        }

        protected void lstProductosCodBarra_KeyDown(object sender, KeyEventArgs e) //captura el evento keyDown cuando se presiona enter sobre lstProductosCodBarra
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesarEleccionLstProductosCodBarra();
            }
            else
            {
                if ((e.KeyCode == Keys.Up) & (lstProductosCodBarra.SelectedIndex == 0))//si llega al primer lugar y presiona para arriba, vuelve al txtCodBarra
                {
                    txtCodBarra.Focus();
                }
            }
        }

        protected void lstProductosDescripcion_KeyDown(object sender, KeyEventArgs e) //captura el evento keyDown cuando se presiona enter sobre lstProductosDescripcion
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesarEleccionLstProductosDescripcion();
            }
            else
            {
                if ((e.KeyCode == Keys.Up) & (lstProductosDescripcion.SelectedIndex == 0)) //si llega al primer lugar y presiona para arriba, vuelve al txtDescripcion
                {
                    txtDescripcion.Focus();
                }

            }
        }
        
        private void txtCodBarra_TextChanged(object sender, EventArgs e)  //si se modifica txtCodBarra, se oculta lstCodBarra
        {
            lstProductosCodBarra.Visible = false;
            lstProductosCodBarra.Enabled = false;
        }


        private void cargarGrilla() //carga la grilla todos los productos vigentes
        {
            try
            {
                productosTa.FillByOrdenadoxDescripcion(centerQuim.Productos); //buscamos productos existentes de manera ordenada

                for (int i = 0; i < centerQuim.Productos.Rows.Count; i++)//cargamos a la grilla
                {
                    if ((centerQuim.Productos[i].tipo == "D") & (centerQuim.Productos[i].litrosEnvase == 0)) 
                    {
                        //si es un disuelto vendido por granel no se carga.
                    }else
                    {
                        
                        dgvProductos.Rows.Add(centerQuim.Productos[i].codProducto, centerQuim.Productos[i].descripcion, centerQuim.Productos[i].stockActual, centerQuim.Productos[i].cantidadMinima, "0", false);
                    }
                    
                }
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.ToString());
            }

        }

        private void colorearGrilla() //asigna colores a las filas según el tipo de productos
        {
            try
            {
                for (int i = 0; i < dgvProductos.Rows.Count; i++) //recorremos el datagride
                {
                    switch (dgvProductos.Rows[i].Cells[1].Value.ToString().Substring(0, 1)) //usamos un según para determinar la primera letra de la descripcion
                    {
                        case "B":
                            dgvProductos.Rows[i].Cells[1].Style.BackColor = Color.PaleGreen;
                            break;
                        case "D":
                            dgvProductos.Rows[i].Cells[1].Style.BackColor = Color.PowderBlue;
                            break;
                        case "T":
                            dgvProductos.Rows[i].Cells[1].Style.BackColor = Color.Beige;
                            break;
                    }
                }

            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.ToString());
            }

        }

        private void btnProcesar_Click(object sender, EventArgs e)
        {
            if (formularioValido())
            {
                try
                {

                    DialogResult result = MessageBox.Show("¿Está seguro que desea generar Orden de Compra", "CONFIRMACION ORDEN DE COMPRA", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                    if (result == DialogResult.Yes)
                    {
                        agregarOrdenCompra();  //agrega un registro de remito a la tabla de Remito

                        agregarProductoxOrdenCompra(); //agrega un registro de productosXRemito a esa tabla

                        //Se muestra un mje de confirmación.
                        MessageBox.Show("Orden de Compra se ha ingresado con exito!!!", "AVISO", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        
                        DialogResult resultado = MessageBox.Show("¿Desea generar un archivo de orden de compra para enviar Casa Central?", "CONFIRMACION ARCHIVO ORDEN DE COMPRA", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                        if (resultado == DialogResult.Yes)
                        {
                            crearArchivo();  //crea el archivo digital para ser enviado a Central.
                        }
                        
                        this.limpiarDatos(); //limpia los datos.

                        imprimir(); //

                    }

                }
                catch (IndexOutOfRangeException)
                {

                }
                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    //Si llega a ocurrir algún error en estado agregar 
                    this.Close();
                }

            }
            else
            {
                informarExistenciaError();
            }
        }

        private void crearArchivo()
        {
            string nombreArchivo; //nombre del archivo para guardar los datos

            int ultimaOrden = ordenTa.ScalarQueryOrdenCompra().Value;

            nombreArchivo = "C:\\Dropbox\\Datos del Sistema\\Ordenes de Compra\\ordenCompra" + ultimaOrden.ToString() + ".cq";

            //guardar el archivo a través del objeto FileStream.
            try
            {
                ordenCompraSalida = new FileStream(nombreArchivo, FileMode.OpenOrCreate, FileAccess.Write); //abre el archivo con acceso de escritura

                CargarDatosAlArchivo();

                MessageBox.Show("Archivo generado con exito!!", "ORDEN DE COMPRA", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            catch (SerializationException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("Error al escribir en el archivo", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            catch (FormatException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("Formato inválido", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            catch (IOException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("Error al abrir el archivo", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                cerrarArchivo();
            }
        }

        private void CargarDatosAlArchivo()
        {
            //-----------ESCRIBE EL ENCABEZADO---------------

            int ultimaOrden = ordenTa.ScalarQueryOrdenCompra().Value; //obtiene el numero de la ultima orden, para el encabezado.

            postTa.Fill(centerQuim.Post); //obtenemos datos del post, para el encabezado.
            
            RegistroOrdenCompra unRegistroOrdenCompra; //instanciamos un registroUsuario(Serializado).

            unRegistroOrdenCompra = new RegistroOrdenCompra(obtenerFechaActual(),cboTurno.SelectedItem.ToString(),ultimaOrden,centerQuim.Post[0].nombre,centerQuim.Post[0].dirección,obtenerUsuarioActual(),"enviado");

            //escribe registro al objeto FileStream (serializa el objeto)
            aplicadorFormato.Serialize(ordenCompraSalida, unRegistroOrdenCompra);

            //-----------ESCRIBE EL CUERPO--------------------

                //actualizamos la tabla productosXordenCompra.
            
            productosxOrdenTa.FillByNroOrdenCompra(centerQuim.ProductosxOrden_Compra, ultimaOrden);

            foreach (DataGridViewRow row in dgvProductos.Rows)
            {
                if (Convert.ToBoolean(row.Cells[5].Value))
                {
                    RegistroProductoOrdenCompra unRegistroProductoOrdenCompra; //instanciamos un registroOrdenCompra(Serializado) y le asignamos nombre.

                    unRegistroProductoOrdenCompra = new RegistroProductoOrdenCompra(Convert.ToString(row.Cells[0].Value), Convert.ToString(row.Cells[1].Value), Convert.ToDouble(row.Cells[2].Value), Convert.ToDouble(row.Cells[3].Value), Convert.ToDouble(row.Cells[4].Value));

                    //escribe registro al objeto FileStream (serializa el objeto)
                    aplicadorFormato.Serialize(ordenCompraSalida, unRegistroProductoOrdenCompra);
                }
                
            }

        }

        private void validarTurno()
        {
            if (cboTurno.Text.Trim() == "")
            {
                errorProvider1.SetError(cboTurno, "Turno: el campo se encuentra vacio\n\n");
            }
            else
            {
                errorProvider1.SetError(cboTurno, "");
            }
        }

        private void verificarCantidadMinima() //si la cantidad es menor a la mínima asigna esta el color de fuente rojo o colarada
        {
            try
            {
                for (int i = 0; i < dgvProductos.Rows.Count; i++) //recorremos el datagride
                {
                    if (Convert.ToDecimal(dgvProductos.Rows[i].Cells[2].Value) < Convert.ToDecimal(dgvProductos.Rows[i].Cells[3].Value))
                    {
                        dgvProductos.Rows[i].Cells[2].Style.ForeColor = Color.Red;
                    }
                }

            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.ToString());
            }

        }

        private bool formularioValido()
        {
            validarTurno();
            validarGrilla();


            if ((errorProvider1.GetError(dgvProductos) == "") & (errorProvider1.GetError(cboTurno) == ""))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void validarGrilla() //recorre todo el dataGride y verifica que los datos se encuentren correctos, si alguno está incorrecto los pinta de blanco
        {
            bool grillaSinError = true;  //inicializa el booleano que controla si el dgvProductos tiene al menos un error.

            bool seleccionado = false; //inicializa el booleano que controla si el dgvProducto tiene al menos un elemento seleccionado
            
            foreach (DataGridViewRow row in dgvProductos.Rows)
            {

                if (Convert.ToBoolean(row.Cells[5].Value))  //si se encuentra seleccionada la fila
                {
                    seleccionado = true;

                    string tipo = Convert.ToString(row.Cells[1].Value).Substring(0, 1);  //obtiene si el tipo de producto en la fila, en base a la primera letra de la descripción

                    if (tipo == "T" || (tipo == "D"))
                    {
                        if ((new ValidarDatos().ValidarNaturalesPositivos("Fila:", Convert.ToString(row.Cells[4].Value))) == "") //No tiene error. El producto terminado o disuelto por cantidad.
                        {
                            row.Cells[4].Style.BackColor = Color.White;

                        }
                        else      //con error en producto terminado o disuelto por cantidad
                        {
                            row.Cells[4].Style.BackColor = Color.LightPink;

                            grillaSinError = false;
                        }

                    }
                    else
                    {
                        if ((new ValidarDatos().validarRealesPositvosSinCero("Fila:", Convert.ToString(row.Cells[4].Value))) == "") //No tiene error. El producto base.
                        {
                            row.Cells[4].Style.BackColor = Color.White;

                        }
                        else  //con error en producto base
                        {
                            row.Cells[4].Style.BackColor = Color.LightPink;

                            grillaSinError = false;
                        }
                    }

                }
                
            }

            if ((grillaSinError) & (seleccionado))
            {
                errorProvider1.SetError(dgvProductos, "");
            }
            else
            {
                if (grillaSinError == false)
                    errorProvider1.SetError(dgvProductos, "Algunos de los campos cantidad en la grilla no contiene datos válidos.");
                
                if (seleccionado == false)
                    errorProvider1.SetError(dgvProductos, "La grilla no contiene productos seleccionados.");
            }

        }

        private void agregarOrdenCompra()
        {
            ordenTa.InsertQueryOrdenCompra(Convert.ToDateTime (obtenerFechaActual()), cboTurno.Text, obtenerCodUsuarioActual());
        }

        private void  agregarProductoxOrdenCompra()
        {
            int ultimaOrden = ordenTa.ScalarQueryOrdenCompra().Value; //obtiene el numero de la ultima orden

            foreach (DataGridViewRow row in dgvProductos.Rows)
            {
                if (Convert.ToBoolean (row .Cells [5].Value ) == true )
                {
                    productosxOrdenTa.InsertQueryProductosxOrdenCompra(ultimaOrden, row.Cells[0].Value.ToString (), row.Cells[1].Value.ToString (), Convert.ToDecimal(row.Cells[4].Value));
                }
            }
        }
 
        private void limpiarDatos()
        {
            dgvProductos.Rows.Clear();
        }

        private void cerrarArchivo()
        {
            try
            {
                if (ordenCompraSalida != null)  //determina si existe el archivo
                {
                    ordenCompraSalida.Close();  //cierra el archivo
                }
            }
            catch (IOException)  //notifica al usuario del error al cerrar el archivo
            {
                MessageBox.Show("No se puede cerrar el archivo.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }


        private void imprimir()
        {
            //buscamos resgistros de la ultima orden
            int ultimaOrden = ordenTa.ScalarQueryOrdenCompra().Value;
            ordenTa.FillByNroOrdenCompra(centerQuim.Orden_de_Compra, ultimaOrden);
            productosxOrdenTa.FillByNroOrdenCompra(centerQuim.ProductosxOrden_Compra, ultimaOrden);

            //Creamos una instancia de un objeto DataTable, y le hacemos que referencie a la tabla en CenterQuimDs.productoXOrden
            DataTable unaDataTable = new DataTable();
            unaDataTable = centerQuim.ProductosxOrden_Compra;

            //creamos una instancia del tipo CrystalReports que habiamos creado y le asignamos a su crvOrdenCompra la tabla instanciada y parametros necesarios.
            crOrdenCompra unCrOrdenCompra = new crOrdenCompra();
            unCrOrdenCompra.SetDataSource(unaDataTable);

            postTa.Fill(centerQuim.Post);
            
            unCrOrdenCompra.SetParameterValue("UnCodigo", "0000"+centerQuim.Orden_de_Compra[0].nroOrdenCompra.ToString());
            unCrOrdenCompra.SetParameterValue("UnaFecha", centerQuim.Orden_de_Compra[0].fechaOrden.ToString("d"));
            unCrOrdenCompra.SetParameterValue("unaDireccion", centerQuim.Post[0].dirección.ToString());
            unCrOrdenCompra.SetParameterValue("unTelefono", centerQuim.Post[0].telefono.ToString());

            //creamos una instancia del frmReporteOrdenCompray le asignamos a su CrystalReportViewer el CrystalReports seteado
            FrmReporteOrdenCompra unFrmReporteOrdenCompra = new FrmReporteOrdenCompra();
            unFrmReporteOrdenCompra.crvOrdenCompra.ReportSource = unCrOrdenCompra;

            //mostramos el frmReporteOrdenCompra
            unFrmReporteOrdenCompra.ShowDialog();
        }

        private string obtenerUsuarioActual()  //Dato necesario para el alta de ListaPrecios
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getNombreUsuario();
        }

        private int obtenerCodUsuarioActual()  //Dato necesario para la apertura de una caja
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getCodUsuario();
        }

        private string obtenerFechaActual()  //Dato necesario para la apertura de una caja.
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getFechaActual();
        }
        

    }

}


